package com.dream21th.common.advisor;

import com.dream21th.common.annotation.CheckValid;
import com.dream21th.common.utils.ThreadData;
import com.dream21th.common.utils.ValidUtils;
import lombok.extern.slf4j.Slf4j;
import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
import org.hibernate.validator.internal.engine.ConstraintViolationImpl;
import javax.validation.ConstraintViolation;
import java.lang.reflect.Parameter;
import java.util.*;

@Slf4j
public class ParamValidateExecutionInterceptor implements MethodInterceptor {

    @Override
    public Object invoke(MethodInvocation invocation) throws Throwable {
        log.info("-------->>>>>>LogExecutionInterceptor");
        try {
            Object[] args = invocation.getArguments();
            Parameter[] parameters = invocation.getMethod().getParameters();
            CheckValid annotationsByType = parameters[0].getDeclaredAnnotation(CheckValid.class);
            Class<?> groupClass = null;
            if (Objects.nonNull(annotationsByType)) {
                groupClass = annotationsByType.value();
            }
            ThreadData.DATA.set(args[0]);
            Set<ConstraintViolation<Object>> validate = ValidUtils.validator().validate(args[0], groupClass);
            List<ConstraintViolation> constraintViolations = Arrays.asList(validate.toArray(new ConstraintViolation[validate.size()]));
            StringBuilder builder = new StringBuilder();
            constraintViolations.stream().sorted(Comparator.comparing(ConstraintViolation::getMessage)).forEach(c -> {
                Map messageParameters = ((ConstraintViolationImpl) c).getMessageParameters();
                if (Objects.nonNull(messageParameters) && messageParameters.get("abc") != null) {
                    builder.append(messageParameters.get("abc"));
                } else {
                    builder.append(c.getMessageTemplate());
                }
                builder.append(";");
            });
            System.out.println(builder.toString());
        } finally {
            ThreadData.DATA.set(null);
        }

        return invocation.proceed();
    }
}
